package org.opsli.modulars.business.iot.coder;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;
import org.opsli.modulars.business.iot.protocol.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.List;

/**
 * @author sst
 * @version V1.0
 * @Package com.lysoft.monitoring.iot.coder
 * @date 2019-08-22 14:22
 * 解码器
 */
public class DecoderHandler extends ByteToMessageDecoder {

    // 消息头：发送端写的是一个int，占用4字节。
    private final static int HEAD_LENGTH = 10;

    /**
     *最小数据长度
     */
    private static int MAIN_DATA_LIN=1+2+6+1+1+1;

    //输出到在线设备采集特有的日志，可以在logback.xml中找
    private final static Logger logger = LoggerFactory.getLogger("devdataLogger");
    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out){
        System.out.println("有消息过来");
        ByteBuf bf = in.copy();
        byte[] bytes =new byte[bf.readableBytes()];
        bf.getBytes(bf.readerIndex(), bytes);
        String str = HexDump.toHexString(bytes);
        System.out.println("设备数据解析结果"+str);
        bf.clear();
        in.clear();
        out.add(str);
       /* if(str.substring(0,2).equals("55")){
            //在线设备
            devDecode(ctx, in, out,bytes,bf);
        }else{
            try {
                strDecode(ctx, in, out,bytes,bf);
            }catch (Exception e){
                e.printStackTrace();
            }
        }*/


    }


    public void devDecode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out,byte[] bytes,ByteBuf bf){
       /* ByteBuf bf = in.copy();
        byte[] bytes =new byte[bf.readableBytes()];
        bf.getBytes(bf.readerIndex(), bytes);*/

        int minLen = in.readableBytes();
        System.out.println(minLen);
        if(minLen>MAIN_DATA_LIN){
            logger.info(HexDump.toHexString(bytes));
            bf.clear();
            logger.debug("开始解码数据");
            in.markReaderIndex();
            byte header =in.readByte();
            if(header == Constans.HEAD_DATA){
                //读取数据长度
                short length = in.readShort();
                byte[] addressByte = new byte[6];
                in.readBytes(addressByte);
                byte identify=in.readByte();
                if(identify==Constans.IDENTIFY){
                    byte anf = in.readByte();
                    //判断是否是在线设备发送过来的数据
                    if(anf==(byte)0x01) {
                        int devCount = in.readByte();
                        List<Dev> list = new ArrayList<>();
                        byte type;
                        for (int i = 0; i < devCount; i++) {
                            type = in.readByte();
                            byte dot = in.readByte();
                            byte unit = in.readByte();
                            int val;
                            byte state;
                            System.out.println("type="+type);
                            if (type == 1) {
                                state = in.readByte();
                                String s = Integer.toBinaryString(state);
                                char fir = s.charAt(0);
                                System.out.println("fir"+fir);
                                //判断是否为温度类型
                                if (fir == '1') {
                                    val = (short)in.readByte();
                                    //温度类型需要分开读取
                                    int c = 0 - val;
                                    val = (short)c;
                                    System.out.println(c);
                                } else {
                                    int c=byteToInteger(in.readByte());
                                 /* val = in.readByte();*/
                                    val=(short)c;
                                }
                            } else {
                                val = in.readUnsignedShort();
                            }

                            state = in.readByte();
                            Dev dev = new Dev(type, dot, unit, val, state);
                            list.add(dev);

                        }
                        byte[] timeByte = new byte[6];
                        in.readBytes(timeByte);
                        in.readByte();
                        byte tail = in.readByte();
                        if (tail == Constans.TAIL) {
                            DevInfo devInfo = new DevInfo(HexDump.toHexString(addressByte), Constans.hexToString(timeByte, false), devCount, list);
                            out.add(devInfo);

                            //回复消息
                            TCPProtocol protocol = new TCPProtocol(addressByte);
                            protocol.setData(new byte[]{0x01});
                            ctx.writeAndFlush(protocol);
                        } else {
                            //logger.error("结束符不正确不正确");
                            System.out.println("结束符不正确不正确");
                            in.clear();
                            ctx.close();
                        }
                    }else if(anf==(byte)0xF1){
                        byte[] temp = new byte[length-11];
                        in.readBytes(temp);
                        in.clear();
                        DevInfo devInfo = new DevInfo(HexDump.toHexString(addressByte), null, 0, null);
                        out.add(devInfo);
                        //
                    }else if(anf==(byte)0xF2){
                        byte[] temp = new byte[length-11];
                        in.readBytes(temp);
                        in.clear();
                    }
                }else{
                    //logger.error("客户身份信息不正确");
                    System.out.println("客户身份信息不正确");
                    //in.clear();
                    ctx.close();
                }

            }else{
                //logger.error("起始字符不正确");
                System.out.println("起始字符不正确");
                in.clear();
                ctx.close();
            }
        }else{
            //logger.error("数据长度不符合要求");
            System.out.println("数据长度不符合要求");
            in.clear();
            ctx.close();
        }
    }

    public static Integer byteToInteger(Byte b) {
        return 0xff & b;
    }

    public void strDecode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out,byte[] bytes,ByteBuf bf) throws Exception{
        String sss = new String(bytes, "UTF-8");
        System.out.println("解析消息内容="+sss);
        bf.clear();
        in.clear();
        out.add(sss);
    }


    protected void strDecode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
        //
        if (in.readableBytes() < HEAD_LENGTH) {
            return;
        }

        // 标记一下当前的readIndex的位置
        in.markReaderIndex();

        // 读取数据长度
        int dataLength = in.readInt();
        // 我们读到的消息体长度为0，这是不应该出现的情况，这里出现这情况，关闭连接。
        if (dataLength < 0) {
            ctx.close();
        }

        //读到的消息体长度如果小于我们传送过来的消息长度，则resetReaderIndex. 这个配合markReaderIndex使用的。把readIndex重置到mark的地方
        if (in.readableBytes() < dataLength) {
            in.resetReaderIndex();
            return;
        }

        // 将缓冲区的数据读到字节数组
        byte[] body = new byte[dataLength];
        in.readBytes(body);
        //将byte数据转化为我们需要的对象。伪代码，用什么序列化，自行选择
        Object msg = convertToObj(body);
        out.add(msg);
    }

    private Object convertToObj(byte[] body) {
        return new String(body,0,body.length);
    }


    /*public void strDecode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out,byte[] bytes,ByteBuf bf) throws Exception{
        String sss = new String(bytes, "UTF-8");
     *//*   System.out.println(sss);*//*
        bf.clear();
        in.clear();
        out.add(sss);
    }*/








}



